//Contains declaration to all the global functions//

#include "projectHeader.h"

unsigned char *GetUOID(char *node_inst_id, char *obj_type, unsigned char *uoid_buf,unsigned int uoid_buf_sz)
{
	static unsigned long seq_no=(unsigned long)1;
	char sha1_buf[SHA_DIGEST_LENGTH], str_buf[104];
	//printf("\nINSIDE UOID ::::::::::::: UOID....\n");
	snprintf(str_buf, sizeof(str_buf), "%s_%s_%1ld",node_inst_id, obj_type, (long)seq_no++);
	SHA1((unsigned char*)str_buf, strlen(str_buf),(unsigned char*) sha1_buf);
	memset(uoid_buf, 0, uoid_buf_sz);
	memcpy(uoid_buf, sha1_buf,min(uoid_buf_sz,sizeof(sha1_buf)));
	//printf("\nUOID is : %s\n",uoid_buf);
	return uoid_buf;
}

void printUOID(unsigned char *uoid)
{
	//printf("UOID = ");
	for(int i=0; i <20 ; i++)
	{
		//printf("%x", uoid[i]);
	}
	//printf("\n");
}

void msgLifetimer()
{
	int timer=0;
	
	while(!((timer==(msgLifeTime+1))/*||(cntrlCFlag))*/))
	{
		pthread_mutex_lock(&cntrlCFlagMutex);
		if(cntrlCFlag)
		{
			pthread_mutex_unlock(&cntrlCFlagMutex);
			break;
		}
		pthread_mutex_unlock(&cntrlCFlagMutex);
		timer++;
	//	printf("TIMER IS %d\n",timer);
		usleep(1000000);

	}
	return;


}



int findBitIndex()
{
	int retIndex=-1;
	for (size_t i=0; i<wQueueIndexBitMap.size(); i++)
	{
		if(wQueueIndexBitMap.test(i)==0)
		{
			wQueueIndexBitMap.set(i,1);
			return i;
		}
	}
	return retIndex;
}


void *get_in_addr(struct sockaddr *sa)
{
	if (sa->sa_family == AF_INET) return &(((struct sockaddr_in*)sa)->sin_addr);
	else return &(((struct sockaddr_in6*)sa)->sin6_addr);
}


void remLeadingSpaces(char *string)
     {
          char *ptr = string;
          for(unsigned int i = 0; i < strlen(string); i++, ptr++)
          {
                if(*ptr != ' ')
                {
					 if(*ptr != '\t')
					{
						 if(*ptr != '\n')
						{
							break;
						}
						
					}

                        
                }
				

          }
          if(*ptr != '\0')
          {
                strcpy(string, ptr);
           }
      }




char * removeTrailingWhiteSpace(char * temp)

{
	int c=0;
	int i=0;
	
	/*for(int j=0;j<100;j++)
	{
		ret[j]='\0';
	}*/
	while(temp[i])
	{
		c=int(temp[i]);
		if (isspace(c))
		{
			temp[i]='\0';
			break;

		}	
		else
		{
			//printf("Value of i is %d and Temp[i] is : %c\n",i,temp[i]);
			
			if(isupper(temp[i]))
			{
				temp[i]=tolower(temp[i]);
			}
			i++;
		}
	}

	return temp;
	
}

char * convertCase(char * temp)

{
	//int c=0;
	int i=0;
	
	/*for(int j=0;j<100;j++)
	{
		ret[j]='\0';
	}*/
	while(temp[i])
	{
		/*
		c=int(temp[i]);
		if (isspace(c))
		{
			temp[i]='\0';
			break;

		}	
		else
		{
			//printf("Value of i is %d and Temp[i] is : %c\n",i,temp[i]);
		*/	
			if(isupper(temp[i]))
			{
				temp[i]=tolower(temp[i]);
			}
			i++;
		//}
	}

	return temp;
	
}

void sendNotifyMsg(char errorCode)
{

	//Populate the notify msg header and data.
	//Make a new queueItem for notify.
	//Push the new queueItem to each of the write threads.
	//printf("ERRORCODE IS %c\n",errorCode);
	if(errorCode == '1' || errorCode == '3')
	{
		//printf("\nEnter if...\n");
	}
	else
	{
		//printf("\nEnter else...\n");
		errorCode = '0';

	}
	queueItem notifyMsgToBeSent;

	notifyMsgClass notifyDataMsg(errorCode);
	//printf("ERRORCODE IS %c\n",errorCode);
	//notifyDataMsg.errorCode = errorCode;
	notifyMsgToBeSent.msgHeader.messageType=0xF7;


	unsigned char *buff1;
	char* msg = (char*)"NTFY";
	buff1=GetUOID((char *)nodeInstanceId,msg,buf, sizeof(buf));
	memcpy(notifyMsgToBeSent.msgHeader.UOID,buf,20);
	
	notifyMsgToBeSent.msgHeader.ttlInHeader=1;
	notifyMsgToBeSent.msgHeader.msgDataLength=1;
	
	memcpy(&(notifyMsgToBeSent.dataBuf[0]),&(notifyDataMsg.errorCode),notifyMsgToBeSent.msgHeader.msgDataLength);
	//printf("ERRORCODE IS %c--->%c\n",notifyMsgToBeSent.dataBuf[0],notifyDataMsg.errorCode);
	//Notify mes ready to me pushed to Queue.
	pthread_mutex_lock(&connectedNodeListMutex);
	pthread_mutex_lock(&sockIndexMapMutex);
	map<int,int>:: iterator notifyIt;
	for(notifyIt=sockFDToQIndexMap.begin();notifyIt!=sockFDToQIndexMap.end();notifyIt++)
	{
		int index= (*notifyIt).second;
		int socketDesc=(*notifyIt).first;
		pthread_mutex_lock(&wrtieQMutex[index]);

			wrtieThreadQueue[index].push_back(notifyMsgToBeSent);
			//printf("SEND NOTIFY FUNCTION: NOTIFY MSG: Msg pushed to writeQueue of %d\n",index);
			pthread_cond_broadcast(&wrtieQCV[index]);

		pthread_mutex_unlock(&wrtieQMutex[index]);

				uint16_t portTemp=0;
	char *tempHost=(char*)malloc(512);
				map<string,int>::iterator it;
				for(it=connectedNodeList.begin() ; it != connectedNodeList.end(); it++ )
				{
					if((*it).second==socketDesc)
					{
								char* str1 = (char*) malloc(512); 
								memset(&str1[0],'\0',512);
								memcpy(&str1[0],&(((*it).first).c_str()[0]),19);

								char *str=(char*)malloc(512);
								memset(str,'\0',512);
								memcpy(&str[0],&str1[0],strlen(str1));
								//printf("String from list is %s\n",str);
								
								tempHost=strtok(str,"_");
								//printf("TempHost is %s and length is %d\n",tempHost,(int)strlen(tempHost));
								char *tempPort=strtok(NULL,"_");
								//printf("TempPort is %s and length is %d\n",tempPort,(int)strlen(tempPort));
								
								portTemp=atoi(tempPort);
								break;
					}
				
				}


				pthread_mutex_lock(&logFileMutex);

				gettimeofday(&tv, NULL); 
				int sec = tv.tv_sec ;
				int msec = tv.tv_usec/1000;
				char *time = (char *)malloc(14);
				memset(time,0,14);
				sprintf(time,"%10ld.%03d",(long)sec,msec);
				time[strlen(time)]='\0';

				



				fprintf(logFilePtr, "s  %s %s:%hu NTFY %d 0x%02x %x%x%x%x %c\n",time,
					tempHost,
					portTemp,
					(notifyMsgToBeSent.msgHeader.msgDataLength+27),
					(unsigned char)notifyMsgToBeSent.msgHeader.ttlInHeader,
					(unsigned char)notifyMsgToBeSent.msgHeader.UOID[16],
					(unsigned char)notifyMsgToBeSent.msgHeader.UOID[17],
					(unsigned char)notifyMsgToBeSent.msgHeader.UOID[18],
					(unsigned char)notifyMsgToBeSent.msgHeader.UOID[19],notifyMsgToBeSent.dataBuf[0]);
					//helloRecvData.HostPort,helloRecvData.Hostname);
				pthread_mutex_unlock(&logFileMutex);


		 
	}
	//terminate=true;
	pthread_mutex_unlock(&sockIndexMapMutex);
	pthread_mutex_unlock(&connectedNodeListMutex);

	return;
}

void retrieveIndexStructure()
{
		/* To write these data structures into permanent file:
				
				list<indexFileMetaInfo> indexFileMetaInfoList;		// list storing information of entire file
				
				map<int,searchResponseInfo> indexSearchResponseMap;	// search filename
				multimap<string,int> indexSHA1Map;						// search sha1
				list<bitVectorIndexItem> indexBitVectoreList;		// search keywords

				map<int,string> numToFileIdMap;						// Mapping from file number to fileID
			*/
			char kwrdIndex[512];
			memset(kwrdIndex,'\0',512);
			memcpy(kwrdIndex,homeDir,strlen(homeDir));
			strcat(kwrdIndex,"/kwrd_index");
			//remove(kwrdIndex);

			char nameIndex[512];
			memset(nameIndex,'\0',512);
			memcpy(nameIndex,homeDir,strlen(homeDir));
			strcat(nameIndex,"/name_index");
			//remove(nameIndex);

			char sha1Index[512];
			memset(sha1Index,'\0',512);
			memcpy(sha1Index,homeDir,strlen(homeDir));
			strcat(sha1Index,"/sha1_index");
			//remove(sha1Index);
			char nameNumIndex[512];
			memset(nameNumIndex,'\0',512);
			memcpy(nameNumIndex,homeDir,strlen(homeDir));
			strcat(nameNumIndex,"/nameNum_index");
			
			
			char numIndex[512];
			memset(numIndex,'\0',512);
			memcpy(numIndex,homeDir,strlen(homeDir));
			strcat(numIndex,"/num_index");


		pthread_mutex_lock(&indexMutex);

		bool numfileExist=false;
		struct stat s4;
		if(stat(numIndex,&s4) == -1){
			//printf("Invalid Path name\n");
			numfileExist=false;
		}
		if (S_ISREG(s4.st_mode))
		{
		  numfileExist=true;
		}
					
		if(numfileExist)
		{
			FILE *numIndexFptr = fopen(numIndex, "r");
			char numIndexFReadBuf[8192];
			memset(&numIndexFReadBuf[0],'\0',8192);

			if(fgets(numIndexFReadBuf,8192,numIndexFptr) != NULL)
			{
				//printf("Buffer Read is %s\n",numIndexFReadBuf);
				//sprintf(fileWriteBuf, "%s-%d-%s-%d-%s-%d-%s\n",tempIndex->originalFileName,tempIndex->numFileName,tempIndex->fileID,(int)tempIndex->filesize,
				//tempIndex->filePassword,tempIndex->isInCache,tempIndex->fileNonceValue);
				
				

				sscanf(numIndexFReadBuf, "%d %d\n",&numFileNameCounter,&remainingCacheSizeInBytes);

				//remainingCacheSizeInBytes=(int)atoi(cache);
				//numFileNameCounter=(int)atoi(numfileId);
				
				
				


			}
			fclose(numIndexFptr);
		}








		bool namefileExist=false;
		struct stat s;
		if(stat(nameIndex,&s) == -1){
			//printf("Invalid Path name\n");
			namefileExist=false;
		}
		if (S_ISREG(s.st_mode))
		{
		  namefileExist=true;
		}
					
		if(namefileExist == true)
		{
			FILE *nameIndexFptr = fopen(nameIndex, "r");
			char nameIndexFReadBuf[8192];
			memset(&nameIndexFReadBuf[0],'\0',8192);

			while (fgets(nameIndexFReadBuf,8192,nameIndexFptr) != NULL)
			{
				//printf("Buffer Read is %s\n",nameIndexFReadBuf);
				//sprintf(fileWriteBuf, "%s-%d-%s-%d-%s-%d-%s\n",tempIndex->originalFileName,tempIndex->numFileName,tempIndex->fileID,(int)tempIndex->filesize,
				//tempIndex->filePassword,tempIndex->isInCache,tempIndex->fileNonceValue);
				
				/*char * originalFileName=strtok(nameIndexFReadBuf,"-");
				char * numFileName=strtok(NULL,"-");
				int tempnumfname=(int)atoi(numFileName);

				char * fileId=strtok(NULL,"-");
				char * filesize=strtok(NULL,"-");
				//if(filesize!=NULL)
				unsigned int tempfsie=(unsigned int)atoi(filesize);

				char * filePassword=strtok(NULL,"-");

				if(filePassword[0]=='g' && filePassword[1]=='\0')
				{
					filePassword[0]='\0';
				}
				char * isInCache=strtok(NULL,"-");
				char * fileNonceValue=strtok(NULL,"\n");
				*/
				int isInCache;
				indexFileMetaInfo tempIndex;
				sscanf(nameIndexFReadBuf, "%s %d %s %u %s %d %s\n",tempIndex.originalFileName,&tempIndex.numFileName,tempIndex.fileID,&tempIndex.filesize,
				tempIndex.filePassword,&isInCache,tempIndex.fileNonceValue);
				
				//printf("%s\n%d\n%s\n%d\n%s\n%d\n%s\n",tempIndex.originalFileName,tempIndex.numFileName,tempIndex.fileID,(int)tempIndex.filesize,
				//tempIndex.filePassword,tempIndex.isInCache,tempIndex.fileNonceValue);

				//printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n",originalFileName,numFileName,fileId,filesize,
				//filePassword,isInCache,fileNonceValue);
				

				/*indexFileMetaInfo temp;
				memcpy(&temp.originalFileName[0],&originalFileName[0],(int)strlen(originalFileName));
				memcpy(&temp.numFileName,&tempnumfname,4);
				memcpy(&temp.fileID[0],&fileId[0],20);
				memcpy(&temp.filesize,&tempfsie,4);
				memcpy(&temp.filePassword[0],&filePassword[0],20);*/
				if (isInCache == 1)
				{
						tempIndex.isInCache = true;
				}
				/*
				memcpy(&temp.fileNonceValue[0],&fileNonceValue[0],40);
				//printf("  %s\n  %d\n  %s\n  %d\n  %s\n  %d\n  %s\n",temp.originalFileName,temp.numFileName,temp.fileID,temp.filesize,
				//temp.filePassword,temp.isInCache,temp.fileNonceValue);
			

				//indexFileMetaInfoList.push_front(temp);*/
				indexFileMetaInfoList.push_front(tempIndex);


			}
			fclose(nameIndexFptr);
		}
//printf("\n\n\n");
		bool kwrdfileExist=false;
		struct stat s1;
		if(stat(kwrdIndex,&s1) == -1){
			//printf("Invalid Path name\n");
			kwrdfileExist=false;
		}
		if (S_ISREG(s1.st_mode))
		{
		  kwrdfileExist=true;
		}
					
		if(kwrdfileExist)
		{
			FILE *kwrdIndexFptr = fopen(kwrdIndex, "r");
			char kwrdIndexFReadBuf[8192];
			memset(&kwrdIndexFReadBuf[0],'\0',8192);

			while (fgets(kwrdIndexFReadBuf,8192,kwrdIndexFptr) != NULL)
			{
				//printf("Buffer Read is %s\n",kwrdIndexFReadBuf);
				
				
/*				char * indexBitVector=strtok(kwrdIndexFReadBuf,"-");
				char * numFileName=strtok(NULL,"\n");
				int tempnumfname=(int)atoi(numFileName);
				//printf("%s\n%s\n",indexBitVector,numFileName);
*/				

				bitVectorIndexItem temp;
				
				//printf("  %s\n  %d\n",temp.indexBitVector,temp.numFileName);
				sscanf(kwrdIndexFReadBuf, "%s %d\n",temp.indexBitVector,&temp.numFileName);
				indexBitVectoreList.push_back(temp);
				


			}
			fclose(kwrdIndexFptr);
		}
		

		//printf("\n\n\n");
		bool sha1fileExist=false;
		struct stat s2;
		if(stat(sha1Index,&s2) == -1){
			//printf("Invalid Path name\n");
			sha1fileExist=false;
		}
		if (S_ISREG(s2.st_mode))
		{
		  sha1fileExist=true;
		}
					
		if(sha1fileExist)
		{
			FILE *sha1IndexFptr = fopen(sha1Index, "r");
			char sha1IndexFReadBuf[8192];
			memset(&sha1IndexFReadBuf[0],'\0',8192);

			while (fgets(sha1IndexFReadBuf,8192,sha1IndexFptr) != NULL)
			{
				//printf("Buffer Read is %s\n",sha1IndexFReadBuf);
				
				
				char tempSha1[512];
				memset(&tempSha1[0],'\0',512);
				
				int tempnumfname=0;
				//printf("%s\n%s\n",indexBitVector,numFileName);
				

				
				
				//printf("  %s\n  %d\n",tempSha1,tempnumfname);
				sscanf(sha1IndexFReadBuf, "%s %d\n",tempSha1,&tempnumfname);
				 indexSHA1Map.insert(pair<string,int>(string(tempSha1,(int)strlen(tempSha1)),tempnumfname));
				


			}
			fclose(sha1IndexFptr);
		}
		



//		printf("\n\n\n");
		bool nameNumfileExist=false;
		struct stat s3;
		if(stat(nameNumIndex,&s3) == -1){
			//printf("Invalid Path name\n");
			nameNumfileExist=false;
		}
		if (S_ISREG(s3.st_mode))
		{
		  nameNumfileExist=true;
		}
					
		if(nameNumfileExist)
		{
			FILE *nameNumIndexFptr = fopen(nameNumIndex, "r");
			char nameNumIndexFReadBuf[8192];
			memset(&nameNumIndexFReadBuf[0],'\0',8192);

			while (fgets(nameNumIndexFReadBuf,8192,nameNumIndexFptr) != NULL)
			{
				//printf("Buffer Read is %s\n",nameNumIndexFReadBuf);
				
				
				//char * num=strtok(nameNumIndexFReadBuf,"-");
				//char * temp=strtok(NULL,"\n");
				//int tempnumfname=(int)atoi(num);
				//printf("%s\n%s\n",indexBitVector,numFileName);
				int tempnum=0;
				char stringbuf[256];
				memset(&stringbuf[0],'\0',256);
				sscanf(nameNumIndexFReadBuf, "%d %s\n",&tempnum,stringbuf);
				
				
				//printf("  %d\n  %s\n",tempnumfname,temp);

				 //numToFileIdMap.insert(pair<int,string>(tempnumfname,string(temp,(int)strlen(temp))));
				numToFileIdMap.insert(pair<int,string>(tempnum,string(stringbuf,(int)strlen(stringbuf))));


			}
			fclose(nameNumIndexFptr);
		}
		
//printf("Retrive Complete.\n");

	pthread_mutex_unlock(&indexMutex);
	return;
}


void writeIndexStructuresToFile()
{
	/* To write these data structures into permanent file:
				
				list<indexFileMetaInfo> indexFileMetaInfoList;		// list storing information of entire file
				
				map<int,searchResponseInfo> indexSearchResponseMap;	// search filename
				map<string,int> indexSHA1Map;						// search sha1
				list<bitVectorIndexItem> indexBitVectoreList;		// search keywords

				map<int,string> numToFileIdMap;						// Mapping from file number to fileID
			*/
			char kwrdIndex[512];
			memset(kwrdIndex,'\0',512);
			memcpy(kwrdIndex,homeDir,strlen(homeDir));
			strcat(kwrdIndex,"/kwrd_index");
			//remove(kwrdIndex);

			char nameIndex[512];
			memset(nameIndex,'\0',512);
			memcpy(nameIndex,homeDir,strlen(homeDir));
			strcat(nameIndex,"/name_index");
			//remove(nameIndex);

			char sha1Index[512];
			memset(sha1Index,'\0',512);
			memcpy(sha1Index,homeDir,strlen(homeDir));
			strcat(sha1Index,"/sha1_index");
			//remove(sha1Index);
			char nameNumIndex[512];
			memset(nameNumIndex,'\0',512);
			memcpy(nameNumIndex,homeDir,strlen(homeDir));
			strcat(nameNumIndex,"/nameNum_index");
			
			
			char numIndex[512];
			memset(numIndex,'\0',512);
			memcpy(numIndex,homeDir,strlen(homeDir));
			strcat(numIndex,"/num_index");

	pthread_mutex_lock(&indexMutex);
	
	// As we need things sorted. Will insert all content of list in multi map. and then write into the multi map.
	multimap<string,indexFileMetaInfo> tempindexNameMultiMap;

	list<indexFileMetaInfo>:: iterator it;
	for(it=indexFileMetaInfoList.begin();it!=indexFileMetaInfoList.end();it++)
	{

		tempindexNameMultiMap.insert(pair<string,indexFileMetaInfo>(string((*it).originalFileName,(int)strlen((*it).originalFileName)),(*it)));
	}
	multimap<string,indexFileMetaInfo>::iterator it1;
	FILE *nameIndexFptr = fopen(nameIndex, "w");
	for(it1=tempindexNameMultiMap.begin();it1!=tempindexNameMultiMap.end();it1++)
	{
		char fileWriteBuf[8192];
		memset(&fileWriteBuf[0],'\0',8192);
		indexFileMetaInfo *tempIndex = (indexFileMetaInfo*) &(*it1).second;

		//printf("%s\n%d\n%s\n::%u\n%s\n%d\n%s\n\n",tempIndex->originalFileName,tempIndex->numFileName,tempIndex->fileID,tempIndex->filesize,
		//		tempIndex->filePassword,tempIndex->isInCache,tempIndex->fileNonceValue);
		if(tempIndex->filePassword[0]=='\0')
			tempIndex->filePassword[0]='g';
		sprintf(fileWriteBuf, "%s %d %s %u %s %d %s\n",tempIndex->originalFileName,tempIndex->numFileName,tempIndex->fileID,tempIndex->filesize,
				tempIndex->filePassword,tempIndex->isInCache,tempIndex->fileNonceValue);
		//printf("Buffer is %s and Length is %d\n",fileWriteBuf,strlen(fileWriteBuf));
		fwrite(fileWriteBuf,1,(int)strlen(fileWriteBuf),nameIndexFptr);
		
	}
	fclose(nameIndexFptr);

	// Now write the bitvector map.
	list<bitVectorIndexItem>::iterator it2;
	FILE *kwrdIndexFptr = fopen(kwrdIndex, "w");
	for(it2=indexBitVectoreList.begin();it2!=indexBitVectoreList.end();it2++)
	{
		char fileWriteBuf[8192];
		memset(&fileWriteBuf[0],'\0',8192);
		bitVectorIndexItem *tempIndex = (bitVectorIndexItem*) &(*it2);

		//printf("%s\n%d\n",tempIndex->indexBitVector,tempIndex->numFileName);

		sprintf(fileWriteBuf, "%s %d\n",tempIndex->indexBitVector,tempIndex->numFileName);
		//printf("Buffer is %s and Length is %d\n",fileWriteBuf,strlen(fileWriteBuf));
		fwrite(fileWriteBuf,1,(int)strlen(fileWriteBuf),kwrdIndexFptr);
		
	}
	fclose(kwrdIndexFptr);


	// Now write the bitvector map.
	map<string,int>::iterator it3;
	FILE *sha1IndexFptr = fopen(sha1Index, "w");
	for(it3=indexSHA1Map.begin();it3!=indexSHA1Map.end();it3++)
	{
		char fileWriteBuf[8192];
		memset(&fileWriteBuf[0],'\0',8192);
		char *tempIndex = (char*) (*it3).first.c_str();
		int *tempnum = (int *) &(*it3).second;
		//printf("%s\n%d\n",tempIndex,*tempnum);

		sprintf(fileWriteBuf, "%s %d\n",tempIndex,*tempnum);
		//printf("Buffer is %s and Length is %d\n",fileWriteBuf,strlen(fileWriteBuf));
		fwrite(fileWriteBuf,1,(int)strlen(fileWriteBuf),sha1IndexFptr);
		
	}
	fclose(sha1IndexFptr);

	map<int,string>::iterator it4;
	FILE *nameNumIndexFptr = fopen(nameNumIndex, "w");
	for(it4=numToFileIdMap.begin();it4!=numToFileIdMap.end();it4++)
	{
		char fileWriteBuf[8192];
		memset(&fileWriteBuf[0],'\0',8192);
		char *tempIndex = (char*) (*it4).second.c_str();
		int *tempnum = (int *) &(*it4).first;
		//printf("%s\n%d\n",*tempnum,tempIndex);

		sprintf(fileWriteBuf, "%d %s\n",*tempnum,tempIndex);
		//printf("Buffer is %s and Length is %d\n",fileWriteBuf,strlen(fileWriteBuf));
		fwrite(fileWriteBuf,1,(int)strlen(fileWriteBuf),nameNumIndexFptr);
		
	}
	fclose(nameNumIndexFptr);
	
	FILE *numIndexFptr = fopen(numIndex, "w");
	
		char fileWriteBuf[8192];
		memset(&fileWriteBuf[0],'\0',8192);
		int *numfileId = (int*)&numFileNameCounter;
		int *cache = (int *) &remainingCacheSizeInBytes ;
		//printf("%s\n%d\n",*numfileId,*cache);

		sprintf(fileWriteBuf, "%d %d\n",*numfileId,*cache);
		//printf("Buffer is %s and Length is %d\n",fileWriteBuf,strlen(fileWriteBuf));
		fwrite(fileWriteBuf,1,(int)strlen(fileWriteBuf),numIndexFptr);
		
	
	fclose(numIndexFptr);



	pthread_mutex_unlock(&indexMutex);
}

void initiateUserShutDownSequence()
{
			errorCode='1';
			sendNotifyMsg(errorCode);
			
			/* To write these data structures into permanent file:
				
				list<indexFileMetaInfo> indexFileMetaInfoList;		// list storing information of entire file
				
				map<int,searchResponseInfo> indexSearchResponseMap;	// search filename
				map<string,int> indexSHA1Map;						// search sha1
				list<bitVectorIndexItem> indexBitVectoreList;		// search keywords

				map<int,string> numToFileIdMap;						// Mapping from file number to fileID
			*/

			writeIndexStructuresToFile();
			sleep(5);
						//printf("Acquire 1.\n");
						pthread_mutex_lock(&sockIndexMapMutex);
						pthread_mutex_lock(&wQBitsetMutex);
							//int index= findBitIndex();
							//printf("Acquire 2.\n");
							map<int,int>::iterator it1;
							//printf("Map Size is %d.\n",(int)sockFDToQIndexMap.size());
							for(it1=sockFDToQIndexMap.begin();it1!=sockFDToQIndexMap.end();it1++)
							{
								int closeSocket=(*it1).first;
								//int resetIndex=(*it).second;
								
								close(closeSocket);
								//printf("Closed Socket: %d\n",closeSocket);	
							}
							wQueueIndexBitMap.reset();
							sockFDToQIndexMap.clear();
							
							//printf("After reseting the maps.\n");
							pthread_mutex_unlock(&wQBitsetMutex);
						pthread_mutex_unlock(&sockIndexMapMutex);
						fclose(initNeighbourListFP);
				fclose(logFilePtr);
				printf("NODE WILL SHUTDOWN NOW.\n");
			exit(0);
		//TODO: close logfile pointer and remove the logfile.
				

		//return;
}


void writeToNAMFile(int statusInputTTL)
{
	//printf("Inside the writer for NAM File.\n");
	//Set the timer for MsgLifeTime or wait till the Crtl+C flag.
	int timer=0;
	
	namFilePtr=fopen(statusFileName,"w");
	fprintf(namFilePtr,"V -t * -v 1.0a5\n");
	if((int)statusRespMap.size()==0)
	{
		fprintf(namFilePtr, "n -t * -s %hu -c red -i black\n",port);
	}
	while(!((timer==(msgLifeTime+1))/*||(cntrlCFlag))*/))
	{
		pthread_mutex_lock(&cntrlCFlagMutex);
		if(cntrlCFlag)
		{
			pthread_mutex_unlock(&cntrlCFlagMutex);
			break;
		}
		pthread_mutex_unlock(&cntrlCFlagMutex);
		timer++;
		//printf("TIMER IS %d\n",timer);
		usleep(1000000);

	}
	//printf("Inside the writer for NAM File.\n");
	//Code to write into the NAM File.
	
	
	 

	if((int)statusRespMap.size()!=0)
	{
		map<int,list<int> > :: iterator it1;

		for(it1=statusRespMap.begin();it1!=statusRespMap.end();it1++)
		{
			int tempPort=(*it1).first;
			fprintf(namFilePtr, "n -t * -s %hu -c red -i black\n",tempPort);
		
		}

		map<int,list<int> > :: iterator it2;

		for(it2=statusRespMap.begin();it2!=statusRespMap.end();it2++)
		{
			int tempPort=(*it2).first;
			list<int> tempList=(*it2).second;
			
			list<int> :: iterator it3;
			for(it3=tempList.begin();it3!=tempList.end();it3++)
			{
				fprintf(namFilePtr, "l -t * -s %hu -d %hu -c blue\n",tempPort,tempList.front());
				tempList.pop_front();
			}
		}

	}
	else
	{
		
	}

	fclose(namFilePtr);






	return;
}

void handlerForCntrlC(int sig)
{
	//printf("Inside SIGINT Handler for Cntrl+C\n");
	pthread_mutex_lock(&cntrlCFlagMutex);
	cntrlCFlag=true;	
	//fprintf(stdin,"\n");
	
	pthread_mutex_unlock(&cntrlCFlagMutex);
}

void softRestart()
{
	softRestartFlag = true;
	errorCode='3';
	sendNotifyMsg(errorCode);
	sleep(5);
	fclose(namFilePtr);
	//re-initalize all the variables.
		port=0;
		autoShutDown=900;
		msgLifeTime=30;
		ttl=30;
		minNeighbour=2;
		keepAliveTimeOut=60;
		initNeighbour=3;
		neighbourStoreProb=0.2;
		cacheProb=0.1;
		cacheSize=500;

		 storeProb=0.1;
		noCheck=0;
		joinTimeOut=15;
		getMsgLifeTime=300;
		 location=0;
		 retry=30;
		 logFileName=NULL;
		 memset(homeDir,'\0',512);


		 portFlag=false;
		 retryFlag=false;
		 locFlag=false;
		 homedirFlag=false;
		 logFileFlag=false;
		 ttlFlag=false;
		 msgLifeTimeFlag=false;
		 minNeighbourFlag=false;
		 autoshutFlag=false;
		 getMsgLifeTimeFlag=false;
		 joinTimeOutFlag=false;
		 storeProbFlag=false;
		 keepAliveTimeoutFlag=false;
		 cacheProbFlag=false;
		 cacheSizeFlag=false;
		 noCheckFlag=false;
		 neighborStoreProbFlag=false;
		 initNeighbourFlag=false;

		checkFlagReceived=false;


		iAmBeacon=false;
		memset(myHostName,'\0',512);
		nodeInstanceId=(char*)malloc(512*sizeof(char));
		fclose(initNeighbourListFP);
		fileOpenSucces=false;
		joinTimeOutBool=false;
		joinTimeOutSockFd=-1;

		 memset(buf,'\0',SHA_DIGEST_LENGTH);


		// reset the bitmap for socket and also close all the sockets.

								
								//printf("Acquire 1.\n");
								pthread_mutex_lock(&sockIndexMapMutex);
								pthread_mutex_lock(&wQBitsetMutex);
									//int index= findBitIndex();
									//printf("Acquire 2.\n");
									map<int,int>::iterator it1;
									//printf("Map Size is %d.\n",(int)sockFDToQIndexMap.size());
									for(it1=sockFDToQIndexMap.begin();it1!=sockFDToQIndexMap.end();it1++)
									{
										int closeSocket=(*it1).first;
										//int resetIndex=(*it).second;
										
										close(closeSocket);
										//printf("Closed Socket: %d\n",closeSocket);	
									}
									wQueueIndexBitMap.reset();
									sockFDToQIndexMap.clear();
									
									//printf("After reseting the maps.\n");
									pthread_mutex_unlock(&wQBitsetMutex);
								pthread_mutex_unlock(&sockIndexMapMutex);


				//reset all the mutex and cond.
				pthread_mutex_init(&connectedNodeListMutex,NULL);
		pthread_mutex_init(&joinTimeOutBoolMutex , NULL);
		pthread_mutex_init(&printMutex , NULL);
		pthread_mutex_init(&wQBitsetMutex,NULL);
		pthread_mutex_init(&sockIndexMapMutex,NULL);
		pthread_mutex_init(&logFileMutex,NULL);
		pthread_mutex_init(&eventQueueMutex,NULL);
		pthread_cond_init(&eventQueueCV,NULL);
		pthread_mutex_init(&keepAliveMapMutex,NULL);
		pthread_mutex_init(&checkTimeoutMutex,NULL);
		pthread_cond_init(&checkTimeoutCV,NULL);
		pthread_mutex_init(&cntrlCFlagMutex,NULL);
		pthread_mutex_init(&UOIDMsgLifeTimeMapMutex,NULL);


		for(int j=0;j<512;j++)
		{
			pthread_mutex_init(&wrtieQMutex[j],NULL);
			pthread_cond_init(&wrtieQCV[j],NULL);
		
		}
								
		//printf("Inside soft restart\n\n");
		joinDistList.clear();
		connectedNodeList.clear();
		eventQueue.clear();
		keepAliveTimers.clear();
		for(int k=0;k<512;k++)
		{
			wrtieThreadQueue[k].clear();
		}
		UOIDMsgLifeTimeMap.clear();
		cntrlCFlag=false;
	//	beaconList.clear();
		statusRespMap.clear();
		nonBeaconList.clear();

			return;
}


void handleAutoShutdown(int sig)
{
	
	//printf("Acquire 1.\n");
	writeIndexStructuresToFile();
	pthread_mutex_lock(&sockIndexMapMutex);
		
		//int index= findBitIndex();
		//printf("Acquire 2.\n");
		map<int,int>::iterator it1;
		//printf("Map Size is %d.\n",(int)sockFDToQIndexMap.size());
		for(it1=sockFDToQIndexMap.begin();it1!=sockFDToQIndexMap.end();it1++)
		{
			int closeSocket=(*it1).first;
			//int resetIndex=(*it).second;
			
			close(closeSocket);
			//printf("Closed Socket: %d\n",closeSocket);	
		}

	pthread_mutex_unlock(&sockIndexMapMutex);
	

				//reset all the mutex and cond.
				pthread_mutex_init(&connectedNodeListMutex,NULL);
		pthread_mutex_init(&joinTimeOutBoolMutex , NULL);
		pthread_mutex_init(&printMutex , NULL);
		pthread_mutex_init(&wQBitsetMutex,NULL);
		pthread_mutex_init(&sockIndexMapMutex,NULL);
		pthread_mutex_init(&logFileMutex,NULL);
		pthread_mutex_init(&eventQueueMutex,NULL);
		pthread_cond_init(&eventQueueCV,NULL);
		pthread_mutex_init(&keepAliveMapMutex,NULL);
		pthread_mutex_init(&checkTimeoutMutex,NULL);
		pthread_cond_init(&checkTimeoutCV,NULL);
		pthread_mutex_init(&cntrlCFlagMutex,NULL);
		pthread_mutex_init(&UOIDMsgLifeTimeMapMutex,NULL);


		for(int j=0;j<512;j++)
		{
			pthread_mutex_init(&wrtieQMutex[j],NULL);
			pthread_cond_init(&wrtieQCV[j],NULL);
		
		}
								
		//printf("Inside soft restart\n\n");
		joinDistList.clear();
		connectedNodeList.clear();
		eventQueue.clear();
		keepAliveTimers.clear();
		for(int k=0;k<512;k++)
		{
			wrtieThreadQueue[k].clear();
		}
		UOIDMsgLifeTimeMap.clear();
		//cntrlCFlag=false;
	//	beaconList.clear();
		statusRespMap.clear();
		nonBeaconList.clear();
fclose(initNeighbourListFP);
	fclose(namFilePtr);
	fclose(logFilePtr);
	printf("\nAutoshutdown time out... Shutting down...\n");
	exit(0);

}



//=========================================================================
//==================Part 2 Updates==============================
//=======================================================================



void calcBitVector(unsigned char* storeFileBitVector)
{

	/*printf("Bit Vector is:\n\n");
	for(int k=0;k<128;k++)
	{
		printf("%x",storeFileBitVector[k]);
	}
	printf("\n");
*/


	
	list<string> ::iterator it1;
	for(it1=storeKeywordsList.begin();it1!=storeKeywordsList.end();it1++)
	{
	//	printf("%s\n",(*it1).c_str());
	//	storeKeywordsList.pop_front();

	char* word = (char *)(*it1).c_str();
	//storeKeywordsList.pop_front();
	char key[512];
	memset(key, '\0',512);
	memcpy(&key[0],&word[0],strlen(word));

	unsigned char sha[20];	//20 bytes
	unsigned char md5[16];	//16 bytes

	int sha1Index;
	int md5Index;

	

	
	MD5_CTX c;
	MD5_Init(&c);
	int len = strlen(key);
	MD5_Update(&c,(void *)key,len);
	
	
	MD5_Final(&md5[0], &c);
	//printf("Calculated MD5: ");
	//	for(unsigned int i=0; i<16;i++)
	//	{
	//		printf("%x",md5[i]);
	//	}
	//	printf("\n");

	/*MD5((unsigned char*)key,len,md5);
	printf("Calculated MD5: ");
		for(unsigned int i=0; i<17;i++)
		{
			printf("%x",md5[i]);
		}
		printf("\n");
	*/


	if ((0x01 & md5[14]) != 0x00)
	{
		md5Index = 256+ (unsigned int)md5[15];
	//		printf("md5Index : %d and md5[15]= %d, %02x\n", md5Index, md5[15], md5[15]);
		
	}
	else{
		md5Index = (unsigned int)md5[15];
		
	//		printf("md5Index : %d\n", md5Index);
		
	}

	
	SHA_CTX c1;
	SHA1_Init(&c1);
	SHA1_Update(&c1,(void *)key,len);
	SHA1_Final(&sha[0], &c1);
	//printf("Calculated SHA1: ");
	//	for(unsigned int i=0; i<20;i++)
	//	{
	//		printf("%x",sha[i]);
	//	}
	//	printf("\n");
	if ((0x01 & sha[18]) != 0x00)
	{
		sha1Index = 256+ (unsigned int)sha[19] +512;
//			printf("sha1Index : %d and sha[19]= %d, %02x\n", sha1Index, sha[19], sha[19]);
		
	}
	else{
		sha1Index = (unsigned int)sha[19]+512;
		
//			printf("sha1Index : %d\n", sha1Index);
		
	}

//	printf("\nBITVECTOR indexes: %d --> %d\n",sha1Index,md5Index);
	if(md5Index<1024)
	{
		//md5Index=0;
		int bitVectorIndex=127- ceil(md5Index/8) ;
		int rem= ((md5Index)%8);
		storeFileBitVector[bitVectorIndex]=storeFileBitVector[bitVectorIndex] | ((unsigned int)1 << rem);
//		printf("bitIndexis %d rem is %d\n",bitVectorIndex,rem);
	}
	if(sha1Index<1024)
	{
		//sha1Index=8;
		int bitVectorIndex=127- ceil(sha1Index/8);
		int rem= ((sha1Index)%8);
		storeFileBitVector[bitVectorIndex]=storeFileBitVector[bitVectorIndex] | ((unsigned int)1 << rem);
//		printf("bitIndexis %d rem is %d\n",bitVectorIndex,rem);
	}
	/*printf("Bit Vector is:\n\n");
	for(int k=0;k<128;k++)
	{
		printf("%x",storeFileBitVector[k]);
	}
	printf("\n");
	*/
}


}


void generateRandChar(char *c)
{
	//srand(10);

	int j=rand()%5;
	while(j!=0)
	{
		rand();
		j--;
	}

	int chance = rand()%2;
	int value=0;
	 //srand(20);
	if (chance == 0)
	{

		 value = rand()%10;
		*c=(char) value+48; 
	}
	else
	{
		value = rand()%6;
		*c=(char) value+97;
	}

//	printf("%c",*c);
}

unsigned char charHexLookupConverter(unsigned char ch)
{
	switch (ch)
	{
	case '0':
		return 0x00;
		break;
	case '1':
		return 0x01;
		break;
	case '2':
		return 0x02;
		break; 
	case '3':
		return 0x03;
		break;
	case '4':
		return 0x04;
		break;
	case '5':
		return 0x05;
		break;
	case '6':
		return 0x06;
		break;
	case '7':
		return 0x07;
		break;
	case '8':
		return 0x08;
		break;
	case '9':
		return 0x09;
		break;
	case 'a':
		return 0x0a;
		break;
	case 'b':
		return 0x0b;
		break;
	case 'c':
		return 0x0c;
		break;
	case 'd':
		return 0x0d;
		break;
	case 'e':
		return 0x0e;
		break;
	case 'f':
		return 0x0f;
		break;
	default:
		return 0x00;
		
	}
}
